/*


 */

package jas.http.server;

import jas.http.logging.HttpLogger;
import jas.http.request.HttpRequest;
import jas.http.request.HttpRequestFormatter;
import jas.http.response.HttpResponse;
import jas.http.response.HttpResponseFactory;
import jas.http.response.ResponseCode;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ThreadPoolExecutor;


/**
 *
 *
 */
public class ThreadedConnectionHandler implements ConnectionHandler,Runnable {
    private HttpResponseFactory responseFactory;
    private HttpLogger logger;
    private Socket clientSocket;
    private ThreadPoolExecutor threadPool;
    
    public ThreadedConnectionHandler (HttpResponseFactory responseFactory, HttpLogger logger, ThreadPoolExecutor threadPool) {
        this.responseFactory = responseFactory;
        this.logger = logger;
        this.threadPool = threadPool;
    }
    

    public void handleConnection(Socket clientSocket) {
        this.clientSocket = clientSocket;
        threadPool.execute(this);
    }

    public void run() {
        try {
            clientSocket.setSoTimeout(1000);
            BufferedReader input = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
            OutputStream output = new BufferedOutputStream(clientSocket.getOutputStream());
            
            HttpResponse httpResponse = null;
            try {
                HttpRequest httpRequest = HttpRequestFormatter.parseRequest(input);
                logger.log(httpRequest.getRequestLine());
                httpResponse = responseFactory.createResponse(httpRequest);
                
                logger.log(httpRequest,httpResponse,clientSocket);
                
            } catch (SocketTimeoutException ex) {
                httpResponse = HttpResponse.createStandardResponse(ResponseCode.BAD_REQUEST);
                
                logger.log("Client timed out, sending BAD REQUEST response.");
            } catch (HttpFormatException ex) {
                httpResponse = HttpResponse.createStandardResponse(ResponseCode.BAD_REQUEST);
                
                logger.log(ex.getMessage());
            }
            
            httpResponse.print(output);
            output.flush();
        }
        catch (SocketException e) {
            
            logger.logError("Socket exception: "+e.getMessage());
        }
        catch (IOException e) { 
            logger.logError("IO exception");
        } catch (RejectedExecutionException ex) {
            
        }
        finally {            
            if (clientSocket != null) {
                try {
                    clientSocket.close();
                } catch (IOException ex) {
                    System.out.println("Meget fucking skidt");
                }
            }
        }
        
    }

    public void stop() {
        threadPool.shutdown();
    }

}
